//
//  LBPageSmoothView.m
//  TEXT
//
//  Created by mac on 2024/8/11.
//  Copyright © 2024 刘博. All rights reserved.
//

#import "ListHeader.h"
#import "LBPageSmoothView.h"
#import "LBObserverCollectionview.h"
#import "LLHeaderContainerView.h"

static NSString *const LIVPageSmoothViewCellID = @"smoothViewCell";

@interface LBPageSmoothCollectionView : UICollectionView <UIGestureRecognizerDelegate>

@property (nonatomic, weak) UIView *headerContainerView;

@end

@implementation LBPageSmoothCollectionView

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    CGPoint point = [touch locationInView:self.headerContainerView];
    ///这里是为了横向滑动头部的时候，不让滑动
    if (CGRectContainsPoint(self.headerContainerView.bounds, point)) {
        return NO;
    }
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
    if ([self isPanBackAction:gestureRecognizer]) {
        return YES;
    }
    return NO;
}

- (BOOL)isPanBackAction:(UIGestureRecognizer *)gestureRecognizer
{
    //在最左边的时候 && 是pan手势，&& 手势往右拖拽
    if (self.contentOffset.x == 0) {
        if (gestureRecognizer == self.panGestureRecognizer) {
            //根据速度判断拖动的方向
            CGPoint velocity = [self.panGestureRecognizer velocityInView:self.panGestureRecognizer.view];
            if (velocity.x > 0) {
                return YES;
            }
        }
    }
    return NO;
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
    if ([self isPanBackAction:gestureRecognizer]) {
        return NO;
    }
    return YES;
}

@end

@interface LBPageSmoothView () <UICollectionViewDelegate, UICollectionViewDataSource>

@property (nonatomic, weak) id<LBPageSmoothViewDataSource> dataSource;
@property (nonatomic, strong) LBPageSmoothCollectionView  *listCollectionView;

/*
 这里面盛放的是列表容器，不是列表视图
 */
@property (nonatomic, strong) NSMutableDictionary <NSNumber *, id<LBPageSmoothListViewDelegate>> *listDict;

/*
 这里面的视图是headerContainerView 的父视图（在没有悬浮的时候），
 其实没有这个的话，直接添加到竖直滚动的列表中也是可以的，
 只不过我们有了这个方便管理
 */
@property (nonatomic, strong) NSMutableDictionary <NSNumber *, ListHeader *> *listHeaderDict;

@property (nonatomic, assign) NSInteger currentIndex;

@property (nonatomic, assign) LBPageSmoothHoverType hoverType;

@property (nonatomic, strong) UIView *headerContainerView;
@property (nonatomic, weak) UIView *headerView;
@property (nonatomic, weak) UIView *segmentedView;
@property (nonatomic, weak) UIScrollView *currentListScrollView;

@property (nonatomic, weak) UIScrollView *lastListScrollView;

@property (nonatomic, assign) BOOL isClickIndex;

/*
 syncListContentOffsetEnabled 是否要同步偏移量
 这个是当我们在头部没有悬浮的时候设置成YES，因为为了要切换
 tab的时候，各个列表的偏移量相同，需要我们将其他列表的偏移量
 设置成和当前列表的偏移量相同，当我们头部悬浮的时候，
 将其他列表的偏移量设置成恰好悬浮的偏移量即可，不需要持续设置
 所以在悬浮的时候，同步过偏移量之后就将syncListContentOffsetEnabled 设置成NO
 没有悬浮的时候需要持续的同步
 */
@property (nonatomic, assign) BOOL syncListContentOffsetEnabled;

/*当前headerContainerView 相对于self的位置.y
 该属性在横向滚动分页视图的时候会用到，因为横向滚动之前，
 我们的headerContainerView视图是添加在纵向滚动的列表视图里面的，为了达到
 头部悬浮的效果，我们需要在横向滚动的时候，将headerContainerView 添加到 self上面
 这个时候就需要我们在纵向滚动的时候，实时的记录headerContainerView 相对于self的
 位置，并且在切换页面之后，使用该位置换算成相对列表的位置，设置纵向列表的偏移量，
 并将headerContainerView 添加到 新的纵向列表上
 */
@property (nonatomic, assign) CGFloat currentHeaderContainerViewY;

///headerContainerView的height， 等于headerHeight  + segmehtheight
@property (nonatomic, assign) CGFloat headerContainerHeight;
///headerView 的height。 headerView顶部视图（不包括segment）
@property (nonatomic, assign) CGFloat headerHeight;
/// segment高度
@property (nonatomic, assign) CGFloat segmentedHeight;

/*
 当前列表视图的初始偏移量
 该属性在这样的场景下起作用：我们在列表1滚动了一定的偏移量，如果列表2还没有创建，
 这时候滑动到列表2 ，列表2 也要滚动相同的偏移量（当然最多是滚动到头部悬浮），这是为了
 切换列表之后，顶部的位置不变，因为没有悬浮的时候，headerContainerView是放在
 列表视图上面的，所以新创建的列表也要设置同样的偏移量 currentListInitializeContentOffsetY
 = 当前的currentListInitializeContentOffsetY 减去当前 headerContainerView相对于
 self的位置（即当前列表滚动实际距离）
 */
@property (nonatomic, assign) CGFloat currentListInitializeContentOffsetY;

@property (nonatomic, assign) BOOL      isLoaded;

@property (nonatomic, assign) BOOL       originShowsVerticalScrollIndicator;

/*
 横向滚动
 */
@property (nonatomic, assign) BOOL       isScroll;
@property (nonatomic, assign) NSInteger  willAppearIndex;
@property (nonatomic, assign) NSInteger  willDisappearIndex;

/*
 正在设置列表的偏移量，正在设置列表的偏移量的时候，
 横向滚动的代理方法中的回调不执行
 */
@property (nonatomic, assign) BOOL       isChangeOffset;


@end

@implementation LBPageSmoothView

- (instancetype)initWithDataSource:(id<LBPageSmoothViewDataSource>)dataSource {
    if (self = [super initWithFrame:CGRectZero]) {
        self.dataSource = dataSource;
        _listDict = [NSMutableDictionary dictionary];
        _listHeaderDict = [NSMutableDictionary dictionary];
        _ceilPointHeight = 0;
        _willAppearIndex = -1;
        _willDisappearIndex = -1;
        
        [self addSubview:self.listCollectionView];
        [self addSubview:self.headerContainerView];
        [self refreshHeaderView];
    }
    return self;
}

- (void)dealloc {
    for (id<LBPageSmoothListViewDelegate> listItem in self.listDict.allValues) {
        [listItem.listScrollView removeObserver:self forKeyPath:@"contentOffset"];
        [listItem.listScrollView removeObserver:self forKeyPath:@"contentSize"];
    }
    
    [self.headerView removeFromSuperview];
    [self.segmentedView removeFromSuperview];
    self.listCollectionView.dataSource = nil;
    self.listCollectionView.delegate = nil;
}

- (void)layoutSubviews {
    [super layoutSubviews];
    
    if (self.listCollectionView.superview == self) {
        [self refreshListFrame:self.bounds];
        self.listCollectionView.frame = self.bounds;
    }
    
    [self.listHeaderDict enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull key, ListHeader * _Nonnull obj, BOOL * _Nonnull stop) {
        CGRect frame = obj.frame;
        frame.origin.y = -self.headerContainerHeight;
        if ([self.listDict[key].listScrollView isKindOfClass:[LBObserverCollectionview class]]) {
            LBObserverCollectionview *scrollView = self.listDict[key].listScrollView;
            frame.origin.y -= scrollView.subSegmentHeight;
            frame.size.height = self.headerContainerHeight;
            obj.backgroundColor = [UIColor magentaColor];
            obj.isSubsegment = YES;
            obj.frame = frame;
        } else {
            frame.size.height = self.headerContainerHeight;
            obj.frame = frame;
            obj.backgroundColor = [UIColor redColor];
        }
    }];
}

- (void)refreshListFrame:(CGRect)frame {
    for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
        CGRect f = list.listView.frame;
        if ((f.size.width != 0 && f.size.width != frame.size.width) || (f.size.height != 0 && f.size.height != frame.size.height)) {
            f.size.width = frame.size.width;
            f.size.height = frame.size.height;
            list.listView.frame = f;
            [self.listCollectionView reloadData];
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.08 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                self.isChangeOffset = YES;
                [self setScrollView:self.listCollectionView offset:CGPointMake(self.currentIndex * frame.size.width, 0)];
            });
        }
    }
}

- (void)refreshHeaderView {
    [self loadHeaderAndSegmentedView];
    [self refreshHeaderContainerView];
}

- (void)refreshSegmentedView {
    self.segmentedView = [self.dataSource segmentedViewInSmoothView:self];
    [self.headerContainerView addSubview:self.segmentedView];
    
    [self refreshHeaderContainerHeight];
    [self refreshHeaderContainerView];
}

- (void)reloadData {
    self.currentListScrollView = nil;
    self.syncListContentOffsetEnabled = NO;
    self.currentHeaderContainerViewY = 0;
    self.isLoaded = YES;
    
    [self.listHeaderDict removeAllObjects];
    
    for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
        [list.listScrollView removeObserver:self forKeyPath:@"contentOffset"];
        [list.listScrollView removeObserver:self forKeyPath:@"contentSize"];
        [list.listView removeFromSuperview];
    }
    [_listDict removeAllObjects];
    
    __weak __typeof(self) weakSelf = self;
    [self refreshWidthCompletion:^(CGSize size) {
        __strong __typeof(weakSelf) self = weakSelf;
        [self setScrollView:self.listCollectionView offset:CGPointMake(size.width * self.currentIndex, 0)];
        [self.listCollectionView reloadData];
        
        // 首次加载
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [self listWillAppear:self.currentIndex];
            [self listDidAppear:self.currentIndex];
        });
    }];
}

- (void)scrollToOriginalPoint {
    [self scrollToOriginalPointAnimated:YES];
}

- (void)scrollToOriginalPointAnimated:(BOOL)animated {
    [self.currentListScrollView setContentOffset:CGPointMake(0, -self.headerContainerHeight) animated:animated];
}

- (void)scrollToCriticalPoint {
    [self scrollToCriticalPointAnimated:YES];
}

- (void)scrollToCriticalPointAnimated:(BOOL)animated {
    [self.currentListScrollView setContentOffset:CGPointMake(0, -(self.segmentedHeight+self.ceilPointHeight)) animated:animated];
}

- (void)setDefaultSelectedIndex:(NSInteger)defaultSelectedIndex {
    _defaultSelectedIndex = defaultSelectedIndex;
    self.currentIndex = defaultSelectedIndex;
}

- (void)updateUIWhenSubContainerScrollViewDidScroll
{
    // 左右滚动的时候，把headerContainerView添加到self，达到悬浮的效果
    if (self.headerContainerView.superview != self) {
        CGRect frame = self.headerContainerView.frame;
        frame.origin.y = self.currentHeaderContainerViewY;
        self.headerContainerView.frame = frame;
        [self addSubview:self.headerContainerView];
    }
}

- (void)updateCurrentListViewWhenContainerDidEndDecelerating
{
    UIView *listHeader = self.listHeaderDict[@(self.currentIndex)];
    UIScrollView *listScrollView = self.listDict[@(self.currentIndex)].listScrollView;
    self.currentListScrollView = listScrollView;
    NSLog(@"哈哈哈哈哈哈哈updateCurrentListViewWhenContainerDidEndDecelerating %f %f %f %d",listScrollView.contentOffset.y,self.segmentedHeight,self.ceilPointHeight,listScrollView.contentOffset.y <= -(self.segmentedHeight + self.ceilPointHeight));
    CGFloat subsegmentHeight = 0;
    if ([listScrollView isKindOfClass:[LBObserverCollectionview class]]) {
        subsegmentHeight = ((LBObserverCollectionview *)listScrollView).subSegmentHeight;
    }
    if (listHeader != nil && listScrollView.contentOffset.y + subsegmentHeight <= -(self.segmentedHeight + self.ceilPointHeight)) {
        for (id<LBPageSmoothListViewDelegate> listItem in self.listDict.allValues) {
            listItem.listScrollView.scrollsToTop = (listItem.listScrollView == listScrollView);
        }
        CGRect frame = self.headerContainerView.frame;
        frame.origin.y = 0;
        self.headerContainerView.frame = frame;
        UIView *listHeader = [self listHeaderForListScrollView:listScrollView];
        listHeader.backgroundColor = [UIColor greenColor];
        if (listHeader.superview != listScrollView) {
            [listScrollView addSubview:listHeader];
        }
        if (self.headerContainerView.superview != listHeader) {
            [listHeader addSubview:self.headerContainerView];
        }
        
        CGFloat minContentSizeHeight = self.bounds.size.height - self.segmentedHeight - self.ceilPointHeight;
        if (minContentSizeHeight > listScrollView.contentSize.height && !self.isHoldUpScrollView) {
            [self setScrollView:listScrollView offset:CGPointMake(listScrollView.contentOffset.x, -self.headerContainerHeight)];
            if (self.listCollectionView.isDragging || self.listCollectionView.isDecelerating) return;
            
            NSInteger listIndex = [self listIndexForListScrollView:listScrollView];
            if (listIndex != self.currentIndex) return;
            CGFloat contentOffsetY = listScrollView.contentOffset.y + self.headerContainerHeight;
            
            if (contentOffsetY < (self.headerHeight - self.ceilPointHeight)) {
                self.hoverType = LBPageSmoothHoverTypeNone;
                self.syncListContentOffsetEnabled = YES;
                self.currentHeaderContainerViewY = -contentOffsetY;
                for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
                    if (list.listScrollView != listScrollView) {
                        [self setScrollView:list.listScrollView offset:listScrollView.contentOffset];
                    }
                    if ([list respondsToSelector:@selector(hasSubSegment)] && [list hasSubSegment]) {
                        [list updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:list.listScrollView contentOffset:listScrollView.contentOffset];
                    }
                }
             
                if (self.headerContainerView.superview != listHeader) {
                    CGRect frame = self.headerContainerView.frame;
                    frame.origin.y = 0;
                    self.headerContainerView.frame = frame;
                    [listHeader addSubview:self.headerContainerView];
                }
                
                if (self.isControlVerticalIndicator && self.ceilPointHeight != 0) {
                    self.currentListScrollView.showsVerticalScrollIndicator = NO;
                }
            }else {
                self.hoverType = LBPageSmoothHoverTypeTop;
                if (self.headerContainerView.superview != self) {
                    CGRect frame = self.headerContainerView.frame;
                    frame.origin.y = - (self.headerHeight - self.ceilPointHeight);
                    self.headerContainerView.frame = frame;
                    [self addSubview:self.headerContainerView];
                }
                
                if (self.isControlVerticalIndicator) {
                    self.currentListScrollView.showsVerticalScrollIndicator = YES;
                }
                
                if (self.syncListContentOffsetEnabled) {
                    self.syncListContentOffsetEnabled = NO;
                    self.currentHeaderContainerViewY = -(self.headerHeight - self.ceilPointHeight);
                    for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
                        if (list.listScrollView != listScrollView) {
                            [self setScrollView:list.listScrollView offset:CGPointMake(0, -(self.segmentedHeight + self.ceilPointHeight))];
                        }
                    }
                }
            }
            CGPoint contentOffset = CGPointMake(listScrollView.contentOffset.x, contentOffsetY);
            if ([self.delegate respondsToSelector:@selector(smoothView:listScrollViewDidScroll:contentOffset:)]) {
                [self.delegate smoothView:self listScrollViewDidScroll:listScrollView contentOffset:contentOffset];
            }

        }
    }
    [self addObserverForListView:listScrollView];
}

- (void)removeObserVerForListView:(UIScrollView *)scrollView
{
    [scrollView removeObserver:self forKeyPath:@"contentOffset"];
    [scrollView removeObserver:self forKeyPath:@"contentSize"];
}

- (void)addObserverForListView:(UIScrollView *)scrollView
{
    [scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
    [scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
}

#pragma mark - UICollectionViewDataSource
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return self.isLoaded ? 1 : 0;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return [self.dataSource numberOfListsInSmoothView:self];
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:LIVPageSmoothViewCellID forIndexPath:indexPath];
    id<LBPageSmoothListViewDelegate> list = self.listDict[@(indexPath.item)];
    if (list == nil) {
        list = [self.dataSource smoothView:self initListAtIndex:indexPath.item];
        if ([list isKindOfClass:UIViewController.class]) {
            UIResponder *next = self.superview;
            while (next != nil) {
                if ([next isKindOfClass:UIViewController.class]) {
                    [((UIViewController *)next) addChildViewController:(UIViewController *)list];
                    break;
                }
                next = next.nextResponder;
            }
        }
        _listDict[@(indexPath.item)] = list;
        [list.listView setNeedsLayout];
        
        UIScrollView *listScrollView = list.listScrollView;
        if ([listScrollView isKindOfClass:[UITableView class]]) {
            ((UITableView *)listScrollView).estimatedRowHeight = 0;
            ((UITableView *)listScrollView).estimatedSectionHeaderHeight = 0;
            ((UITableView *)listScrollView).estimatedSectionFooterHeight = 0;
        }
        if (@available(iOS 11.0, *)) {
            listScrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        }
        
        if (listScrollView) {
            CGFloat minContentSizeHeight = self.bounds.size.height - self.segmentedHeight - self.ceilPointHeight;
            if (listScrollView.contentSize.height < minContentSizeHeight && self.isHoldUpScrollView) {
                listScrollView.contentSize = CGSizeMake(self.bounds.size.width, minContentSizeHeight);
            }
        }
        
        UIEdgeInsets insets = listScrollView.contentInset;
        insets.top = self.headerContainerHeight;
        if ([listScrollView isKindOfClass:[LBObserverCollectionview class]]) {
            insets = ((LBObserverCollectionview *)listScrollView).oroginalContentInset;
            insets.top = insets.top + ((LBObserverCollectionview *)listScrollView).subSegmentHeight;
        }
        listScrollView.contentInset = insets;
        self.currentListInitializeContentOffsetY = -listScrollView.contentInset.top + MIN(-self.currentHeaderContainerViewY, (self.headerHeight - self.ceilPointHeight));
        NSLog(@"哈哈哈哈哈哈哈cellForItemAtIndexPath %f %f", insets.top, self.currentListInitializeContentOffsetY);
        [self setScrollView:listScrollView offset:CGPointMake(0, self.currentListInitializeContentOffsetY)];
        if ([list respondsToSelector:@selector(hasSubSegment)] && [list hasSubSegment]) {
            [list updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:listScrollView contentOffset:CGPointMake(0, self.currentListInitializeContentOffsetY)];
            [list updateOtherSublistScrollViewContentWithCurrentListScroll:listScrollView contentInset:insets];
        }
        UIView *listHeader = [[ListHeader alloc] initWithFrame:CGRectMake(0, -self.headerContainerHeight, self.bounds.size.width, self.headerContainerHeight)];
        [listScrollView addSubview:listHeader];
        if (self.headerContainerView.superview == nil) {
            [listHeader addSubview:self.headerContainerView];
        }
        self.listHeaderDict[@(indexPath.item)] = listHeader;
        
        [listScrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
        [listScrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
        // bug fix #69 修复首次进入时可能出现的headerView无法下拉的问题
        [listScrollView setContentOffset:listScrollView.contentOffset];
        if ([list respondsToSelector:@selector(hasSubSegment)] && [list hasSubSegment]) {
            [list updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:listScrollView contentOffset:listScrollView.contentOffset];
        }
    }
    for (id<LBPageSmoothListViewDelegate> listItem in self.listDict.allValues) {
        listItem.listScrollView.scrollsToTop = (listItem == list);
        if ([listItem respondsToSelector:@selector(hasSubSegment)] && [listItem hasSubSegment]) {
            [listItem configScrollsTopWithScrollView:list.listScrollView];
        }
    }
    
    UIView *listView = list.listView;
    if (listView != nil && listView.superview != cell.contentView) {
        [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
        listView.frame = cell.bounds;
        [cell.contentView addSubview:listView];
    }
    return cell;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
    for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
        list.listView.frame = (CGRect){{0, 0}, self.listCollectionView.bounds.size};
    }
    return self.listCollectionView.bounds.size;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    if (self.isChangeOffset) {
        self.isChangeOffset = NO;
        return;
    }
    
    if ([self.delegate respondsToSelector:@selector(smoothView:scrollViewDidScroll:)]) {
        [self.delegate smoothView:self scrollViewDidScroll:scrollView];
    }
    
    if (self.isClickIndex) {
        return;
    }
    
    CGFloat indexPercent = scrollView.contentOffset.x/scrollView.bounds.size.width;
    NSInteger index = floor(indexPercent);
    self.isScroll = YES;
    
    UIScrollView *listScrollView = self.listDict[@(index)].listScrollView;
    if (index != self.currentIndex && indexPercent - index == 0 && !(scrollView.isDragging || scrollView.isDecelerating) && listScrollView.contentOffset.y <= -(self.segmentedHeight + self.ceilPointHeight)) {
        [self horizontalScrollDidEndAtIndex:index];
    }else {
        // 左右滚动的时候，把headerContainerView添加到self，达到悬浮的效果
        if (self.headerContainerView.superview != self) {
            CGRect frame = self.headerContainerView.frame;
            frame.origin.y = self.currentHeaderContainerViewY;
            self.headerContainerView.frame = frame;
            [self addSubview:self.headerContainerView];
        }
    }
    
    if (!scrollView.isDragging && !scrollView.isTracking && !scrollView.isDecelerating) {
        return;
    }
    CGFloat ratio = scrollView.contentOffset.x/scrollView.bounds.size.width;
    NSInteger maxCount = round(scrollView.contentSize.width/scrollView.bounds.size.width);
    NSInteger leftIndex = floorf(ratio);
    leftIndex = MAX(0, MIN(maxCount - 1, leftIndex));
    NSInteger rightIndex = leftIndex + 1;
    if (ratio < 0 || rightIndex >= maxCount) {
        [self listDidAppearOrDisappear:scrollView];
        return;
    }
    if (rightIndex == self.currentIndex) {
        //当前选中的在右边，用户正在从右边往左边滑动
        if (self.listDict[@(leftIndex)] != nil) {
            if (self.willAppearIndex == -1) {
                self.willAppearIndex = leftIndex;
                [self listWillAppear:self.willAppearIndex];
            }
        }
        if (self.willDisappearIndex == -1) {
            self.willDisappearIndex = rightIndex;
            [self listWillDisappear:self.willDisappearIndex];
        }
    }else {
        //当前选中的在左边，用户正在从左边往右边滑动
        if (self.listDict[@(rightIndex)] != nil) {
            if (self.willAppearIndex == -1) {
                self.willAppearIndex = rightIndex;
                [self listWillAppear:self.willAppearIndex];
            }
        }
        if (self.willDisappearIndex == -1) {
            self.willDisappearIndex = leftIndex;
            [self listWillDisappear:self.willDisappearIndex];
        }
    }
    [self listDidAppearOrDisappear:scrollView];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        // 滑动到一半又取消滑动处理
        if (self.willDisappearIndex != -1) {
            [self listWillAppear:self.willDisappearIndex];
            [self listWillDisappear:self.willAppearIndex];
            [self listDidAppear:self.willDisappearIndex];
            [self listDidDisappear:self.willAppearIndex];
            self.willDisappearIndex = -1;
            self.willAppearIndex = -1;
        }
    }
    if (!decelerate) {
        NSInteger index = scrollView.contentOffset.x / scrollView.bounds.size.width;
        [self horizontalScrollDidEndAtIndex:index];
    }
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    // 滑动到一半又取消滑动处理
    if (self.willDisappearIndex != -1) {
        [self listWillAppear:self.willDisappearIndex];
        [self listWillDisappear:self.willAppearIndex];
        [self listDidAppear:self.willDisappearIndex];
        [self listDidDisappear:self.willAppearIndex];
        self.willDisappearIndex = -1;
        self.willAppearIndex = -1;
    }
    NSInteger index = scrollView.contentOffset.x / scrollView.bounds.size.width;
    [self horizontalScrollDidEndAtIndex:index];
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
    if (!self.isLoaded) return;
    // 修复快速闪烁问题
    NSInteger index = scrollView.contentOffset.x / scrollView.bounds.size.width;
    self.currentIndex = index;
    self.currentListScrollView = self.listDict[@(index)].listScrollView;
    self.isScroll = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.15 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        if (!self.isScroll && self.headerContainerView.superview == self) {
            [self horizontalScrollDidEndAtIndex:index];
        }
    });
}

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqualToString:@"contentOffset"]) {
        UIScrollView *scrollView = (UIScrollView *)object;
        if (scrollView != nil) {
            [self listScrollViewDidScroll:scrollView];
        }
    }else if ([keyPath isEqualToString:@"contentSize"]) {
        UIScrollView *scrollView = (UIScrollView *)object;
        if (scrollView != nil) {
            CGFloat minContentSizeHeight = self.bounds.size.height - self.segmentedHeight - self.ceilPointHeight;
            CGFloat contentH = scrollView.contentSize.height;
            if (minContentSizeHeight > contentH && self.isHoldUpScrollView) {
                scrollView.contentSize = CGSizeMake(scrollView.contentSize.width, minContentSizeHeight);
                // 新的scrollView第一次加载的时候重置contentOffset
                if (self.currentListScrollView != nil && scrollView != self.currentListScrollView) {
                    if (!CGSizeEqualToSize(scrollView.contentSize, CGSizeZero)) {
                        [self setListScrollView:scrollView offset:CGPointMake(0, self.currentListInitializeContentOffsetY)];
                    }
                }
            }else {
                BOOL shouldReset = YES;
                for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
                    if (list.listScrollView == scrollView && [list respondsToSelector:@selector(listScrollViewShouldReset)]) {
                        shouldReset = [list listScrollViewShouldReset];
                    }
                }
                
                if (minContentSizeHeight > contentH && shouldReset) {
                    [self setListScrollView:scrollView offset:CGPointMake(scrollView.contentOffset.x, -self.headerContainerHeight)];
                    [self listScrollViewDidScroll:scrollView];
                }
            }
        }
    }else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}

#pragma mark - Private Methods
- (void)listWillAppear:(NSInteger)index {
    if (![self checkIndexValid:index]) return;
    id<LBPageSmoothListViewDelegate> list = _listDict[@(index)];
    if (list && [list respondsToSelector:@selector(listViewWillAppear)]) {
        [list listViewWillAppear];
    }
}

- (void)listDidAppear:(NSInteger)index {
    if (![self checkIndexValid:index]) {
        return;
    }
    self.currentIndex = index;
    id<LBPageSmoothListViewDelegate> list = _listDict[@(index)];
    if (list && [list respondsToSelector:@selector(listViewDidAppear)]) {
        [list listViewDidAppear];
    }
}

- (void)listWillDisappear:(NSInteger)index {
    if (![self checkIndexValid:index]) {
        return;
    }
    
    id<LBPageSmoothListViewDelegate> list = _listDict[@(index)];
    if (list && [list respondsToSelector:@selector(listViewWillDisappear)]) {
        [list listViewWillDisappear];
    }
}

- (void)listDidDisappear:(NSInteger)index {
    if (![self checkIndexValid:index]) {
        return;
    }
    id<LBPageSmoothListViewDelegate> list = _listDict[@(index)];
    if (list && [list respondsToSelector:@selector(listViewDidDisappear)]) {
        [list listViewDidDisappear];
    }
}

- (BOOL)checkIndexValid:(NSInteger)index {
    NSUInteger count = [self.dataSource numberOfListsInSmoothView:self];
    if (count <= 0 || index >= count) {
        return NO;
    }
    return YES;
}

- (void)listDidAppearOrDisappear:(UIScrollView *)scrollView {
    CGFloat currentIndexPercent = scrollView.contentOffset.x/scrollView.bounds.size.width;
    if (self.willAppearIndex != -1 || self.willDisappearIndex != -1) {
        NSInteger disappearIndex = self.willDisappearIndex;
        NSInteger appearIndex = self.willAppearIndex;
        if (self.willAppearIndex > self.willDisappearIndex) {
            //将要出现的列表在右边
            if (currentIndexPercent >= self.willAppearIndex) {
                self.willDisappearIndex = -1;
                self.willAppearIndex = -1;
                [self listDidDisappear:disappearIndex];
                [self listDidAppear:appearIndex];
            }
        }else {
            //将要出现的列表在左边
            if (currentIndexPercent <= self.willAppearIndex) {
                self.willDisappearIndex = -1;
                self.willAppearIndex = -1;
                [self listDidDisappear:disappearIndex];
                [self listDidAppear:appearIndex];
            }
        }
    }
}

- (void)listScrollViewDidScroll:(UIScrollView *)scrollView {
    if (self.listCollectionView.isDragging || self.listCollectionView.isDecelerating) return;
    
    NSInteger listIndex = [self listIndexForListScrollView:scrollView];
    if (listIndex != self.currentIndex) return;
    self.currentListScrollView = scrollView;
    CGFloat contentOffsetY = scrollView.contentOffset.y + self.headerContainerHeight;
    CGFloat subSegmentHeight = 0;
    NSLog(@"哈哈哈哈哈哈哈这里这里listScrollViewDidScroll scrollView.contentOffset.y%f, self.headerContainerHeight %f contentOffsetY %f", contentOffsetY, self.headerContainerHeight, contentOffsetY);
    if ([scrollView isKindOfClass:[LBObserverCollectionview class]]) {
       // subSegment  = ((LBObserverCollectionview *)scrollView).subSegmentHeight;
        contentOffsetY +=  ((LBObserverCollectionview *)scrollView).subSegmentHeight;
        subSegmentHeight = ((LBObserverCollectionview *)scrollView).subSegmentHeight;
    }
    NSLog(@"哈哈哈哈哈哈这里这里listScrollViewDidScroll%f %f", contentOffsetY,(self.headerHeight - self.ceilPointHeight));
    if (contentOffsetY < (self.headerHeight - self.ceilPointHeight)) {
        NSLog(@"哈哈哈哈哈这里执行了执行了listScrollViewDidScroll contentOffsetY < (self.headerHeight - self.ceilPointHeight) ");
        self.hoverType = LBPageSmoothHoverTypeNone;
        self.syncListContentOffsetEnabled = YES;
        self.currentHeaderContainerViewY = -contentOffsetY;
        for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
         
            if (list.listScrollView != scrollView) {
                if ([list.listScrollView isKindOfClass:[LBObserverCollectionview class]]) {
                    if ([scrollView isKindOfClass:[LBObserverCollectionview class]]) {
                        [self setScrollView:list.listScrollView offset:scrollView.contentOffset];
                    } else {
                        subSegmentHeight = ((LBObserverCollectionview *)list.listScrollView).subSegmentHeight;
                        [self setScrollView:list.listScrollView offset:CGPointMake(0, scrollView.contentOffset.y - subSegmentHeight)];
                    }
                } else {
                    if ([scrollView isKindOfClass:[LBObserverCollectionview class]]) {
                        [self setScrollView:list.listScrollView offset:CGPointMake(0, scrollView.contentOffset.y + subSegmentHeight)];
                    } else {
                        [self setScrollView:list.listScrollView offset:scrollView.contentOffset];
                    }
                }
            }
          
            if ([list respondsToSelector:@selector(hasSubSegment)] && [list hasSubSegment]) {
                CGFloat extraHeight = 0;
                if (![scrollView isKindOfClass:[LBObserverCollectionview class]]) {
                    extraHeight = ((LBObserverCollectionview *)list.listScrollView).subSegmentHeight;
                }
                [list updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:scrollView contentOffset:CGPointMake(0, scrollView.contentOffset.y - extraHeight)];
            }
        }
        UIView *listHeader = [self listHeaderForListScrollView:scrollView];
        if (listHeader.superview != scrollView) {
            [scrollView addSubview:listHeader];
        }
        if (self.headerContainerView.superview != listHeader && !self.isClickIndex) {
            CGRect frame = self.headerContainerView.frame;
            frame.origin.y = 0;
            self.headerContainerView.frame = frame;
            [listHeader addSubview:self.headerContainerView];
        }
        
        if (self.isControlVerticalIndicator && self.ceilPointHeight != 0) {
            self.currentListScrollView.showsVerticalScrollIndicator = NO;
        }
    }else {
        self.hoverType = LBPageSmoothHoverTypeTop;
        if (self.headerContainerView.superview != self) {
            CGRect frame = self.headerContainerView.frame;
            frame.origin.y = - (self.headerHeight - self.ceilPointHeight);
            self.headerContainerView.frame = frame;
            [self addSubview:self.headerContainerView];
        }
        
        if (self.isControlVerticalIndicator) {
            self.currentListScrollView.showsVerticalScrollIndicator = YES;
        }
        
        if (self.syncListContentOffsetEnabled) {
            self.syncListContentOffsetEnabled = NO;
            self.currentHeaderContainerViewY = -(self.headerHeight - self.ceilPointHeight);
            for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
                if (list.listScrollView != scrollView) {
                    [self setScrollView:list.listScrollView offset:CGPointMake(0, -(self.segmentedHeight + self.ceilPointHeight))];
                }
                if ([list respondsToSelector:@selector(hasSubSegment)] && [list hasSubSegment]) {
                    [list updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:scrollView contentOffset:scrollView.contentOffset];
                }
            }
        }
    }
    CGPoint contentOffset = CGPointMake(scrollView.contentOffset.x, contentOffsetY);
    if ([self.delegate respondsToSelector:@selector(smoothView:listScrollViewDidScroll:contentOffset:)]) {
        [self.delegate smoothView:self listScrollViewDidScroll:scrollView contentOffset:contentOffset];
    }
}

- (void)loadHeaderAndSegmentedView {
    self.headerView = [self.dataSource headerViewInSmoothView:self];
    self.segmentedView = [self.dataSource segmentedViewInSmoothView:self];
    [self.headerContainerView addSubview:self.headerView];
    [self.headerContainerView addSubview:self.segmentedView];
    
    // 刷新高度
    [self refreshHeaderContainerHeight];
}

- (void)refreshHeaderContainerView {
    __weak __typeof(self) weakSelf = self;
    [self refreshWidthCompletion:^(CGSize size) {
        __strong __typeof(weakSelf) self = weakSelf;
        [self refreshHeaderContainerHeight];
        
        CGRect frame = self.headerContainerView.frame;
        if (CGRectEqualToRect(frame, CGRectZero)) {
            frame = CGRectMake(0, 0, size.width, self.headerContainerHeight);
        }else {
            frame.size.height = self.headerContainerHeight;
        }
        self.headerContainerView.frame = frame;
        
        self.headerView.frame = CGRectMake(0, 0, size.width, self.headerHeight);
        self.segmentedView.frame =  CGRectMake(0, self.headerHeight, size.width, self.segmentedHeight);
        
        if (self.segmentedView.superview != self.headerContainerView) { // 修复headerHeight < size.height, headerContainerHeight > size.height时segmentedView.superView为bottomContainerView
            [self.headerContainerView addSubview:self.segmentedView];
        }
        
        for (id<LBPageSmoothListViewDelegate> list in self.listDict.allValues) {
            UIEdgeInsets insets = list.listScrollView.contentInset;
            insets.top = self.headerContainerHeight;
            list.listScrollView.contentInset = insets;
            if ([list respondsToSelector:@selector(updateOtherSublistScrollViewContentWithCurrentListScroll:contentInset:)]) {
                [list updateOtherSublistScrollViewContentWithCurrentListScroll:list.listScrollView contentInset:insets];
            }
            [self setScrollView:list.listScrollView offset:CGPointMake(0, -self.headerContainerHeight)];
            if ([list respondsToSelector:@selector(updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:contentOffset:)]) {
                [list updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:list.listScrollView contentOffset:CGPointMake(0, -self.headerContainerHeight)];
            }
        }
        for (UIView *listHeader in self.listHeaderDict.allValues) {
            CGRect frame = listHeader.frame;
            frame.origin.y = -self.headerContainerHeight;
            frame.size.height = self.headerContainerHeight;
            listHeader.frame = frame;
        }
    }];
}

- (void)refreshHeaderContainerHeight {
    self.headerHeight = self.headerView.bounds.size.height;
    self.segmentedHeight = self.segmentedView.bounds.size.height;
    self.headerContainerHeight = self.headerHeight + self.segmentedHeight;
}

- (void)refreshWidthCompletion:(void(^)(CGSize size))completion {
    if (self.bounds.size.width == 0) {
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            !completion ? : completion(self.bounds.size);
        });
    }else {
        !completion ? : completion(self.bounds.size);
    }
}

- (void)horizontalScrollDidEndAtIndex:(NSInteger)index {
    UIScrollView *lastScrollView = self.lastListScrollView;

    self.currentIndex = index;
    UIView *listHeader = self.listHeaderDict[@(index)];
    UIScrollView *listScrollView = self.listDict[@(index)].listScrollView;
    self.currentListScrollView = listScrollView;
    self.lastListScrollView = self.currentListScrollView;
    NSLog(@"哈哈哈哈哈哈哈嘎嘎嘎嘎这里的偏移量哈哈哈%f %f %@", listScrollView.contentOffset.y,-(self.segmentedHeight + self.ceilPointHeight), listScrollView);
    CGFloat subSegmentHeight = 0;
    if (![lastScrollView isKindOfClass:[LBObserverCollectionview class]] && [listScrollView isKindOfClass:[LBObserverCollectionview class]]) {
        subSegmentHeight = ((LBObserverCollectionview *)listScrollView).subSegmentHeight;
    }
    if (listHeader != nil && listScrollView.contentOffset.y + subSegmentHeight <= -(self.segmentedHeight + self.ceilPointHeight)) {
        for (id<LBPageSmoothListViewDelegate> listItem in self.listDict.allValues) {
            listItem.listScrollView.scrollsToTop = (listItem.listScrollView == listScrollView);
        }
        CGRect frame = self.headerContainerView.frame;
        frame.origin.y = 0;
        if (self.isClickIndex) {
            frame.origin.y = self.currentHeaderContainerViewY;
        }
        self.headerContainerView.frame = frame;
        if (self.headerContainerView.superview != listHeader && !self.isClickIndex) {
            [listHeader addSubview:self.headerContainerView];
        }
        if (listHeader.superview != listScrollView) {
            [listScrollView addSubview:listHeader];
        }
        
        CGFloat minContentSizeHeight = self.bounds.size.height - self.segmentedHeight - self.ceilPointHeight;
        if (minContentSizeHeight > listScrollView.contentSize.height && !self.isHoldUpScrollView) {
            [self setScrollView:listScrollView offset:CGPointMake(listScrollView.contentOffset.x, -self.headerContainerHeight)];
            [self listScrollViewDidScroll:listScrollView];
        }
    }
}

- (UIView *)listHeaderForListScrollView:(UIScrollView *)scrollView {
    for (NSNumber *index in self.listDict) {
        if (self.listDict[index].listScrollView == scrollView) {
            return self.listHeaderDict[index];
        }
    }
    return nil;
}

- (NSInteger)listIndexForListScrollView:(UIScrollView *)scrollView {
    for (NSNumber *index in self.listDict) {
        if (self.listDict[index].listScrollView == scrollView) {
            return index.integerValue;
        }
    }
    return 0;
}

- (void)setListScrollView:(UIScrollView *)scrollView offset:(CGPoint)offset {
    if (!CGPointEqualToPoint(scrollView.contentOffset, offset)) {
        [scrollView setContentOffset:offset animated:NO];
    }
    
    for (NSNumber *index in self.listDict) {
        id<LBPageSmoothListViewDelegate> list = self.listDict[index];
        if ([list respondsToSelector:@selector(updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:contentOffset:)]) {
            [list updateOtherSublistScrollViewContentOffsetWithCurrentListScroll:list.listScrollView contentOffset:offset];
        }
    }
}

- (void)setScrollView:(UIScrollView *)scrollView offset:(CGPoint)offset
{
    if (!CGPointEqualToPoint(scrollView.contentOffset, offset)) {
        [scrollView setContentOffset:offset animated:NO];
    }
}

#pragma mark - Getter
- (UICollectionView *)listCollectionView {
    if (!_listCollectionView) {
        UICollectionViewFlowLayout *layout = [UICollectionViewFlowLayout new];
        layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
        layout.minimumLineSpacing = 0;
        layout.minimumInteritemSpacing = 0;
        _listCollectionView = [[LBPageSmoothCollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
        _listCollectionView.dataSource = self;
        _listCollectionView.delegate = self;
        _listCollectionView.pagingEnabled = YES;
        _listCollectionView.bounces = NO;
        _listCollectionView.showsHorizontalScrollIndicator = NO;
        _listCollectionView.showsVerticalScrollIndicator = NO;
        _listCollectionView.scrollsToTop = NO;
        [_listCollectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:LIVPageSmoothViewCellID];
        if (@available(iOS 11.0, *)) {
            _listCollectionView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
        }
        if (@available(iOS 10.0, *)) {
            _listCollectionView.prefetchingEnabled = NO;
        }
        _listCollectionView.headerContainerView = self.headerContainerView;
    }
    return _listCollectionView;
}

- (UIView *)headerContainerView {
    if (!_headerContainerView) {
        _headerContainerView = [LLHeaderContainerView new];
    }
    return _headerContainerView;
}

- (void)selectIndex:(NSInteger)index;
{
    if (self.isClickIndex == YES) {
        return;
    }
    self.isClickIndex = YES;
    UIScrollView *listScrollView = self.listDict[@(index)].listScrollView;
    // 左右滚动的时候，把headerContainerView添加到self，达到悬浮的效果
    if (self.headerContainerView.superview != self) {
        CGRect frame = self.headerContainerView.frame;
        NSLog(@"哈哈哈啊哈哈这里这里这里这里currentHeaderContainerViewY%f", self.currentHeaderContainerViewY);
        frame.origin.y = self.currentHeaderContainerViewY;
        self.headerContainerView.frame = frame;
        [self addSubview:self.headerContainerView];
    }
    [self.listCollectionView setContentOffset:CGPointMake(self.bounds.size.width * index, 0) animated:YES];
    listScrollView.scrollEnabled = NO;
    self.currentIndex = index;
    self.currentListScrollView = listScrollView;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.isClickIndex = NO;
        listScrollView.scrollEnabled = YES;
    });
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

@end
